
#include "RobboLito.h"
#include "RobboTripleBase.h"
#include <string.h>
#include "RobboTotalBase.h"

static char ENUMn[65] =
  { A1, A2, B1, B2, A3, A4, B3, B4, C1, C2, D1, D2, C3, C4, D3, D4,
    A8, A7, B8, B7, A6, A5, B6, B5, C8, C7, D8, D7, C6, C5, D6, D5,
    H1, H2, G1, G2, H3, H4, G3, G4, F1, F2, E1, E2, F3, F4, E3, E4,
    H8, H7, G8, G7, H6, H5, G6, G5, F8, F7, E8, E7, F6, F5, E6, E5, -1 };
static char ENUM0[2] = { -2, -1 };

static char ENUM_BI_PED[49] =
  { A2, B2, C2, D2, E2, F2, G2, H2, A3, B3, C3, D3, E3, F3, G3, H3,
    A4, B4, C4, D4, E4, F4, G4, H4, A5, B5, C5, D5, E5, F5, G5, H5,
    A6, B6, C6, D6, E6, F6, G6, H6, A7, B7, C7, D7, E7, F7, G7, H7, -1 };

static char ENUM_NE_PED[49] =
  { A7, B7, C7, D7, E7, F7, G7, H7, A6, B6, C6, D6, E6, F6, G6, H6,
    A5, B5, C5, D5, E5, F5, G5, H5, A4, B4, C4, D4, E4, F4, G4, H4,
    A3, B3, C3, D3, E3, F3, G3, H3, A2, B2, C2, D2, E2, F2, G2, H2, -1 };

static char ENUM_ALF[65] =
  { A1, A3, B2, C1, A5, B4, C3, D2, E1, A7, B6, C5, D4, E3, F2, G1,
    B8, C7, D6, E5, F4, G3, H2, D8, E7, F6, G5, H4, F8, G7, H6, H8,
    H1, H3, G2, F1, H5, G4, F3, E2, D1, H7, G6, F5, E4, D3, C2, B1,
    G8, F7, E6, D5, C4, B3, A2, E8, D7, C6, B5, A4, C8, B7, A6, A8, -1 };

static char ENUM_BLOCKED[41] =
  { A2, B2, C2, D2, E2, F2, G2, H2, A3, B3, C3, D3, E3, F3, G3, H3,
    A4, B4, C4, D4, E4, F4, G4, H4, A5, B5, C5, D5, E5, F5, G5, H5,
    A6, B6, C6, D6, E6, F6, G6, H6, -1 };

/**************************************************/

#define fputI(u, a, F) \
  { int j; for (j = 0; j < u; j++) fputc ( (a >> (8 * j)) & 255, file); }
#define MEMORIA_CONTROL(A, pro, c, N) \
  { if (c > pro - 10) { pro += pro / 4; A = realloc (A, pro * N); } }

#define SPUT(r, ch) \
  { L[l++] = (r << 2) + ch; MEMORIA_CONTROL(L, Lpr, l, 4); }
#define PROSSIMO(u) E[w++] = u; if ( (w % PROP) == 0) ok = FALSE;
#define BYTEw(r, ff, tr) \
  { uint8 by = r % 32; ok = TRUE; \
    if (r >= 32) by += 128; if (tr) by += 64; if (ff) by += 32; PROSSIMO(by); \
    r -= (r % 32); r >>= 5; \
    while (r && ok) { by = ( r >= 128 ) * 128 + ( r % 128 ); \
                      r -= ( r % 128 ); r >>= 7; PROSSIMO(by); } }

#define SetVal(ARR, loc, v) { ARR[loc >> 2] |= (v << (2 * (loc & 3)) ); loc++; }
#define GetVal(ARR, i) (((ARR[(i) >> 2]) >> (2 * ((i) & 3))) & 3)

static void rle (char* b, int c, char* NOME, int* C) /* split this function */
{
  int *L, *I, i, l = 0, r = 0, w = 0, id = 0;
  int A[4], AB[4], la = 0, sb = 0, Ii = 0, PROP;
  char FN[256], ok = 0; /* bugfix */
  int Epr = 32 + c / 1024, Ipr = 32 + c / 1024, Lpr = 32 + c / 1024;
  uint8 *E;
  boolean tr, ff;
  uint8 ch;
  int cu, te;
  FILE *file;
  char TEMP[32];
  char DIR_NAME[256];
#ifdef NOME_WINDOWS
#define FIVE_PIECE_LENGTH 7
#else
#define FIVE_PIECE_LENGTH 3
#endif
#ifdef ROBBO_PICCOLO
  if (strlen (NOME) == FIVE_PIECE_LENGTH)
    PROP = 64;
  else
    PROP = 16;
#else
  PROP = 16;
#endif
  if (C[1] > C[2])
    {
      if (C[3] > C[1])
	{
	  A[3] = 1;
	  A[1] = 2;
	  A[2] = 3;
	}
      else if (C[3] > C[2])
	{
	  A[1] = 1;
	  A[3] = 2;
	  A[2] = 3;
	}
      else
	{
	  A[1] = 1;
	  A[2] = 2;
	  A[3] = 3;
	}
    }
  else
    {
      if (C[3] > C[2])
	{
	  A[3] = 1;
	  A[2] = 2;
	  A[1] = 3;
	}
      else if (C[3] > C[1])
	{
	  A[2] = 1;
	  A[3] = 2;
	  A[1] = 3;
	}
      else
	{
	  A[2] = 1;
	  A[1] = 2;
	  A[3] = 3;
	}
    }
  for (i = 1; i <= 3; i++)
    AB[A[i]] = i;
  if (C[AB[2]] == 0)
    {
      strcpy(TEMP, NOME);
      if (TEMP[0] == 'K' || TEMP[0] =='k')
	un_windows_triple (TEMP);
      sprintf (FN, "%s/%d/%s%s", TRIPLE_DIR, (int) strlen (TEMP) + 2,
	       TRIPLE_PREFISSO, NOME);
      file = fopen (FN, "w");
      fputc (AB[1], file);
      fputc (0, file);
      fclose (file);
      file = 0;
      sprintf (DIR_NAME, "%s/%d/", TRIPLE_DIR, (int) strlen (TEMP) +2);
      load_triple (NOME, DIR_NAME);
      return;
    }
  E = malloc (Epr);
  I = malloc (Ipr * sizeof (int));
  L = malloc (Lpr * sizeof (int));
  Ii = 1;
  SetVal (b, c, 0);
  c--;
  cu = GetVal (b, 0);
  for (i = 1; i <= c; i++) /* make run lengths */
    {
      te = GetVal (b, i);
      if (cu == te)
	{
	  r++;
	  continue;
	}
      r++;
      SPUT (r, cu); /* store run in L[l++] */ /* why a macro? */
      cu = te;
      r = 0;
    }
  i = 0;
  while (i < l) /* l as size of RLE encoded array */
    {
      r = L[i] >> 2; /* length of run */ /* limit 2^29 ? */
      ch = L[i] & 3; /* value */
      id += r;
      if (!la)
	{
	  if (ch != AB[1])
	    sb = la = AB[1];
	  else
	    sb = la = AB[2];
	}
      if (la == AB[1])
	{
	  if (ch == AB[2])
	    tr = FALSE;
	  else
	    tr = TRUE;
	}
      else
	{
	  if (ch == AB[1])
	    tr = FALSE;
	  else
	    tr = TRUE;
	}
      ff = FALSE;
      if (r == 1 && i > 0 && i < l - 1 && (L[i - 1] & 3) == (L[i + 1] & 3)
	  && (w % PROP)) /* flip for run length 1 */
	{
	  ff = TRUE;
	  r = L[++i] >> 2;
	  ch = L[i] & 3;
	  id += r;
	}
      else
	la = ch;
      BYTEw (r, ff, tr); /* encode byte into E array as E[w++] */
      i++;
      MEMORIA_CONTROL (E, Epr, w, 1);
      if ((w % PROP) == 0) /* demonstrate index on 64-byte boundary */
	{
	  I[Ii++] = (id << 2) + ch; /* index and value as 2 bits */
	  MEMORIA_CONTROL (I, Ipr, Ii, 4);
	}
    }
  free (L);
  for (i = w % PROP; i < PROP; i++) /* fill as zeroes */
    {
      E[w++] = 0;
      MEMORIA_CONTROL (E, Epr, w, 1);
    }
  strcpy(TEMP, NOME);
  if (TEMP[0] == 'K' || TEMP[0]=='k')
    un_windows_triple (TEMP);
  sprintf (FN, "%s/%d/%s%s", TRIPLE_DIR, (int) strlen (TEMP) + 2,
	   TRIPLE_PREFISSO, NOME);
  file = fopen (FN, "w");
  I[Ii] = (c << 2); /* ignored */
  I[0] = sb; /* bugfix */
  fputc (AB[1], file);
  fputc (AB[2], file);
  fputc (AB[3], file);
  fputc (0, file);
  fputI (4, w, file); /* ENDIAN ok */
  fputI (4, c, file); /* ENDIAN ok */
  fputI (2, PROP, file); /* ENDIAN ok */
  fputc (0, file);
  fputc (0, file);
  for (i = 0; i < Ii; i++)
    fputI (4, I[i], file); /* ENDIAN ok */
  free (I);
  for (i = 0; i < w; i++)
    fputc (E[i], file);
  fflush (file);
  fclose (file);
  free (E);
  file = 0;
}

/**************************************************/

#define wEnumB wEnumBL
#define bEnumB bEnumBL

void TripleBaseMake (typePOS* POSITION, char* PEZZO, char* inome_file)
{
  int check = 0, u, MODO = vNON, mal = 0, TotalBase = 0, vc, v[4], w = 0;
  int b, s, cattvi = 0, cattpa = 0, L[4];
  int bK, wK, move, to, fr, pb = 0, c2 = 0, pr, pi, cp;
  const short int *PILA;
  char *TH, *E[4];
  uint64 O, SIZE;
  int rip = 0, p, C[4];
  typeMoveList LIST[256], *list;
  int i, j, k, rf, RF;
  char nome_file[256];

#ifdef NOME_WINDOWS
  nome_file[0] = 'K';
  j = 0;
  while (inome_file[j])
    {
      if (inome_file[j] <= 'Z')
	{
	  nome_file[2 * j + 1] = 'w';
	  nome_file[2 * j + 2] = inome_file[j] + 32;
	}
      else
	{
	  nome_file[2 * j + 1] = 'b';
	  nome_file[2 * j + 2] = inome_file[j];
	}
      j++;
    }
  nome_file[2 * j + 1] = 0;
#else
  strcpy(nome_file, inome_file);
#endif

  printf ("TripleBaseMake %s\n", nome_file);
  POSITION->wtm = TRUE;
  p = 0;
  PILA = RE_normale;
  for (i = 0; i < 4; i++)
    if (PEZZO[i] == wEnumP || PEZZO[i] == bEnumP || PEZZO[i] == BlockedPawn)
      PILA = RE_pedone;
  C[0] = C[1] = C[2] = C[3] = 0;
  POSITION->DYN->reversible = 0;
  POSITION->DYN->ep = POSITION->DYN->oo = 0;
  for (i = 0; i < 4; i++)
    {
      E[i] = ENUMn;
      if (!PEZZO[i])
	E[i] = ENUM0;
      if (PEZZO[i] == wEnumP)
	E[i] = ENUM_BI_PED;
      if (PEZZO[i] == bEnumP)
	E[i] = ENUM_NE_PED;
      if (PEZZO[i] == BlockedPawn)
	E[i] = ENUM_BLOCKED;
      if (PEZZO[i] == wEnumB || PEZZO[i] == bEnumB)
	E[i] = ENUM_ALF;
    }
  SIZE = 355100000 / 4;
  TH = malloc (SIZE);
  for (i = 0; i < SIZE; i++)
    TH[i] = 0;
  for (u = A1; u <= H8; u++)
    POSITION->sq[u] = 0;
  RF = (PILA == RE_pedone) ? 1806 : 462;
  for (rf = 0; rf < RF; rf++)
    {
      if (PILA == RE_normale)
	{
	  wK = inverso_normale_re[rf] >> 6;
	  bK = inverso_normale_re[rf] & 63;
	}
      if (PILA == RE_pedone)
	{
	  wK = inverso_pedone_re[rf] >> 6;
	  bK = inverso_pedone_re[rf] & 63;
	}
      if (PEZZO[2] && (PILA[64 * wK + bK] & 15) == 0)
	printf ("%c%c %c%c %d %d\n", (wK & 7) + 'a', (wK / 8) + '1',
		(bK & 7) + 'a', (bK / 8) + '1', w, PILA[64 * wK + bK]);
      for (L[0] = 0; (v[0] = E[0][L[0]]) != -1; L[0]++)
	for (L[1] = 0; (v[1] = E[1][L[1]]) != -1; L[1]++)
	  for (L[2] = 0; (v[2] = E[2][L[2]]) != -1; L[2]++)
	    for (L[3] = 0; (v[3] = E[3][L[3]]) != -1; L[3]++)
	      {
		if (PEZZO[1] && PEZZO[0] == PEZZO[1] && L[1] >= L[0])
		  continue;
		if (PEZZO[2] && PEZZO[1] == PEZZO[2] && L[2] >= L[1])
		  continue;
		if (PEZZO[3] && PEZZO[2] == PEZZO[3] && L[3] >= L[2])
		  continue;
		POSITION->wKsq = wK;
		POSITION->bKsq = bK;
		wBitboardK = SqSet[wK];
		bBitboardK = SqSet[bK];
		wBitboardQ = wBitboardR = wBitboardN = wBitboardBD =
		  wBitboardBL = wBitboardP = 0;
		bBitboardQ = bBitboardR = bBitboardN = bBitboardBD =
		  bBitboardBL = bBitboardP = 0;
		for (i = 0; i < 4; i++)
		  {
		    if (PEZZO[i] != BlockedPawn)
		      POSITION->bitboard[PEZZO[i]] |= SqSet[v[i]];
		    else
		      {
			POSITION->bitboard[wEnumP] |= SqSet[v[i]];
			POSITION->bitboard[bEnumP] |= SqSet[v[i] + 8];
		      }
		  }		
		wBitboardOcc = wBitboardP | wBitboardN |
		  wBitboardB | wBitboardR | wBitboardQ | wBitboardK;
#ifndef MAGIC_BITBOARDS
		POSITION->OccupiedL90 = POSITION->OccupiedL45 =
		  POSITION->OccupiedR45 = 0;
#endif
		bBitboardOcc = bBitboardP | bBitboardN |
		  bBitboardB | bBitboardR | bBitboardQ | bBitboardK;
		O = wBitboardOcc | bBitboardOcc;
		POSITION->OccupiedBW = O;
		for (i = 0; i < 4; i++)
		  {
		    if (PEZZO[i] && PEZZO[i] != BlockedPawn)
		      POSITION->sq[v[i]] = PEZZO[i];
		    if (PEZZO[i] == BlockedPawn)
		      {
			POSITION->sq[v[i]] = wEnumP;
			POSITION->sq[v[i] + 8] = bEnumP;
		      }
		    if (PEZZO[i] == wEnumB && SqSet[v[i]] & LIGHT)
		      POSITION->sq[v[i]] = wEnumBL;
		    if (PEZZO[i] == wEnumB && SqSet[v[i]] & DARK)
		      POSITION->sq[v[i]] = wEnumBD;
		    if (PEZZO[i] == bEnumB && SqSet[v[i]] & LIGHT)
		      POSITION->sq[v[i]] = bEnumBL;
		    if (PEZZO[i] == bEnumB && SqSet[v[i]] & DARK)
		      POSITION->sq[v[i]] = bEnumBD;
		  }
		POSITION->wtm = TRUE;
		POSITION->sq[POSITION->wKsq] = wEnumK;
		POSITION->sq[POSITION->bKsq] = bEnumK;
#ifndef MAGIC_BITBOARDS
		while (O)
		  {
		    b = BSF (O);
		    POSITION->OccupiedL90 |= SqSet[Left90[b]];
		    POSITION->OccupiedL45 |= SqSet[Left45[b]];
		    POSITION->OccupiedR45 |= SqSet[Right45[b]];
		    BitClear (b, O);
		  }
#endif
		POSITION->wtm = TRUE;
		Mobility (POSITION);
#define IN_CHECK (wBitboardK & POSITION->DYN->bAtt)
#ifdef ROBBO_SCACCO
		if (IN_CHECK && PEZZO[2]) /* safe with Z */
		  {
		    check++;
		    SetVal (TH, w, MODO);
		    goto LOOP;
		  }
#endif

#define IS_ILLEGAL \
  (POSITION->wtm ? \
   (bBitboardK & POSITION->DYN->wAtt) : (wBitboardK & POSITION->DYN->bAtt) )
#define BAD \
  ( (PEZZO[1] && v[0] == v[1]) || (PEZZO[2] && v[0] == v[2]) || \
    (PEZZO[3] && v[0] == v[3]) || (PEZZO[2] && v[1] == v[2]) || \
    (PEZZO[3] && v[1] == v[3]) || (PEZZO[3] && v[2] == v[3]) || \
    (v[0] == POSITION->wKsq) || (v[1] == POSITION->wKsq) || \
    (v[2] == POSITION->wKsq) || (v[3] == POSITION->wKsq) || \
    (v[0] == POSITION->bKsq) || (v[1] == POSITION->bKsq) || \
    (v[2] == POSITION->bKsq) || (v[3] == POSITION->bKsq) || \
    (PEZZO[0] == BlockedPawn && \
     ((v[0] + 8) == v[1] || (v[0] + 8 == v[2]) || (v[0] + 8 == v[3]) \
      || (v[0] + 8) == POSITION->wKsq || (v[0] + 8) == POSITION->bKsq)) || \
    (PEZZO[1] == BlockedPawn && \
     ((v[1] + 8) == v[0] || (v[1] + 8 == v[2]) || (v[1] + 8 == v[3]) \
      || (v[1] + 8) == POSITION->wKsq || (v[1] + 8) == POSITION->bKsq)) || \
    (PEZZO[2] == BlockedPawn && \
     ((v[2] + 8) == v[0] || (v[2] + 8 == v[1]) || (v[2] + 8 == v[3]) \
      || (v[2] + 8) == POSITION->wKsq || (v[2] + 8) == POSITION->bKsq)) || \
    (PEZZO[3] == BlockedPawn && \
     ((v[3] + 8) == v[0] || (v[3] + 8 == v[1]) || (v[3] + 8 == v[2]) \
      || (v[3] + 8) == POSITION->wKsq || (v[3] + 8) == POSITION->bKsq)) \
    || IS_ILLEGAL)
		if (BAD || !RobboTotalBaseScore (POSITION, &s) || s == dROTT)
		  {
		    mal++;
		    SetVal (TH, w, MODO);
		    goto LOOP;
		  }
		if (DISCO_PATTA (s) && MODO == ePAT)
		  {
		    C[2]++;
		    rip++;
		    SetVal (TH, w, MODO);
		    goto LOOP;
		  }
		if (DISCO_VITTORIA (s) && MODO == eVIT)
		  {
		    C[1]++;
		    rip++;
		    SetVal (TH, w, MODO);
		    goto LOOP;
		  }
		if (DISCO_PERDITA (s) && MODO == ePER)
		  {
		    C[3]++;
		    rip++;
		    SetVal (TH, w, MODO);
		    goto LOOP;
		  }
		list = GenCapturesTotal (POSITION, LIST);
		for (u = 0; u < list - LIST; u++)
		  {
		    move = LIST[u].move;
		    to = TO (move);
		    fr = FROM (move);
		    cp = POSITION->sq[to];
		    pr = MoveIsProm (move);
		    pi = POSITION->sq[fr];
		    POSITION->bitboard[cp] ^= SqSet[to];
		    POSITION->bitboard[pi] ^= SqSet[to] ^ SqSet[fr];
		    if (pi == wEnumK)
		      POSITION->wKsq = to;
		    wBitboardOcc ^= SqSet[to] ^ SqSet[fr];
		    if (cp)
		      bBitboardOcc ^= SqSet[to];
		    POSITION->OccupiedBW =  wBitboardOcc | bBitboardOcc;
#ifndef MAGIC_BITBOARDS
		    POSITION->OccupiedL90 ^=  SqSet[Left90[fr]];
		    POSITION->OccupiedL45 ^= SqSet[Left45[fr]];
		    POSITION->OccupiedR45 ^= SqSet[Right45[fr]];
		    if (!cp)
		      {
			POSITION->OccupiedL90 ^= SqSet[Left90[to]];
			POSITION->OccupiedL45 ^= SqSet[Left45[to]];
			POSITION->OccupiedR45 ^= SqSet[Right45[to]];
		      }
#endif
		    if (pr && ((move >> 12) & 7) == 7)
		      {
			wBitboardP ^= SqSet[to];
			wBitboardQ ^= SqSet[to];
		      }
		    POSITION->sq[to] = pi;
		    if (pr)
		      POSITION->sq[to] = wEnumQ;
		    POSITION->wtm = FALSE;
		    Mobility (POSITION);
		    if (!IS_ILLEGAL && RobboTotalBaseScore (POSITION, &vc))
		      pb++;
		    else
		      vc = 1000;
		    c2++;
		    POSITION->wtm = TRUE;
		    POSITION->bitboard[cp] ^= SqSet[to];
		    POSITION->bitboard[pi] ^= SqSet[fr];
		    if (pi == wEnumK)
		      POSITION->wKsq = fr;
		    POSITION->sq[fr] = pi;
		    POSITION->sq[to] = cp;
		    wBitboardOcc ^= SqSet[to] ^ SqSet[fr];
		    if (cp)
		      bBitboardOcc ^= SqSet[to];
		    POSITION->OccupiedBW = wBitboardOcc | bBitboardOcc;
#ifndef MAGIC_BITBOARDS
		    POSITION->OccupiedL90 ^= SqSet[Left90[fr]];
		    POSITION->OccupiedL45 ^= SqSet[Left45[fr]];
		    POSITION->OccupiedR45 ^= SqSet[Right45[fr]];
		    if (!cp)
		      {
			POSITION->OccupiedL90 ^= SqSet[Left90[to]];
			POSITION->OccupiedL45 ^= SqSet[Left45[to]];
			POSITION->OccupiedR45 ^= SqSet[Right45[to]];
		      }
#endif
		    if (pr && ((move >> 12) & 7) == 7)
		      {
			wBitboardP ^= SqSet[to];
			wBitboardQ ^= SqSet[to];
		      }
		    if (pr && ((move >> 12) & 7) == 4)
		      {
			wBitboardP ^= SqSet[to];
			wBitboardN ^= SqSet[to];
		      }
		    if (vc != 1000 && DISCO_PERDITA (vc))
		      {
			cattvi++;
			SetVal (TH, w, MODO);
			goto LOOP;
		      }
		    if (vc != 1000 && DISCO_PATTA (vc) && DISCO_PATTA (s)
			&& GetVal (TH, w - 1) != eVIT && GetVal (TH, w - 1) != vNON)
		      {
			cattpa++;
			SetVal (TH, w, MODO);
			goto LOOP;
		      }
		  }
		POSITION->wtm = TRUE;
		if (DISCO_PATTA (s))
		  {
		    C[2]++;
		    MODO = ePAT;
		  }
		if (DISCO_VITTORIA (s))
		  {
		    C[1]++;
		    MODO = eVIT;
		  }
		if (DISCO_PERDITA (s))
		  {
		    C[3]++;
		    MODO = ePER;
		  }
		SetVal (TH, w, MODO);
		TotalBase++;
	      LOOP:
		for (i = 0; i < 4; i++)
		  {
		    if (PEZZO[i])
		      POSITION->sq[v[i]] = 0;
		    if (PEZZO[i] == BlockedPawn)
		      POSITION->sq[v[i] + 8] = 0;
		  }
		POSITION->sq[POSITION->wKsq] = 0;
		POSITION->sq[POSITION->bKsq] = 0;
	      }
    }
  printf ("s%d 210:%d/%d/%d\nmal:%d sc:%d cat:%d/%d"
	  " rip:%d RTB:%d\ntot:%d/%d pb:%d/%d\n",
	  C[0], C[1], C[2], C[3], mal,
	  check, cattvi, cattpa, rip, TotalBase,
	  mal + check + cattvi + cattpa + rip + TotalBase, w, pb, c2);
  i = 0;
  while (GetVal (TH, i) == vNON)
    i++;
  s = GetVal (TH, i);
  j = 0;
  while (j <= i)
    SetVal (TH, j, s);
  rle (TH, w, nome_file, C);
  free (TH);
}

/**************************************************/

static void simmetria (char *C, char *SIM) /* Z base? */
{
  int i;
  for (i = 0; C[i]; i++)
    SIM[i] = C[i] ^ 32;
  SIM[i] = 0;
}

#define RECURSE(C, B) \
  if (cog_triple (C) == 0) \
    { if (B) { printf ("Recursing %s\n", C); triple_disposto (C, B); } \
      else { printf ("Needed dependency %s unavailable\n", C); \
	     while (1); return; } }

void triple_disposto (char *II, boolean B)
{
  int i, j, n;
  boolean simm = FALSE;
  char C[16], SIM[16], PEZb[8] = "QRBN", PEZn[8] = "qrbn", A[16];
  char PI[4];
  char I[32];
  typePOS POSITION[1];
  strcpy(I, II);
  if (I[0] == 'K' || A[0]=='k')
    un_windows_triple (I);
  strcpy (A, I);
  for (n = strlen (A); n < 4; n++)
    A[n] = 0;
  n = nome_canonico (A, &simm);
  strcpy (C, A);
  for (i = 0; i < n; i++)
    {
      if (C[i] == 'P')
	{
	  for (j = 0; j < 4; j++)
	    {
	      C[i] = PEZb[j];
	      RECURSE (C, B);
	      simmetria (C, SIM);
	      RECURSE (SIM, B);
	    }
	  C[i] = 'P';
	}
      if (C[i] == 'p')
	{
	  for (j = 0; j < 4; j++)
	    {
	      C[i] = PEZn[j];
	      RECURSE (C, B);
	      simmetria (C, SIM);
	      RECURSE (SIM, B);
	    }
	  C[i] = 'p';
	}
      if (C[i] == 'Z')
        {
          C[i] = 'P';
          RECURSE (C, B);
          simmetria (C, SIM);
          RECURSE (SIM, B);
          C[i] = 'p';
          RECURSE (C, B);
          simmetria (C, SIM);
          RECURSE (SIM, B);
          C[i] = 'Z';
        }
    }
  for (i = 0; i < n; i++)
    {
      C[i] = A[n - 1];
      C[n - 1] = 0;
      RECURSE (C, B);
      C[i] = A[i];
    }
  for (i = 0; i < 4; i++)
    switch (I[i])
      {
      case 'Q':
	PI[i] = wEnumQ;
	continue;
      case 'q':
	PI[i] = bEnumQ;
	continue;
      case 'R':
	PI[i] = wEnumR;
	continue;
      case 'r':
	PI[i] = bEnumR;
	continue;
      case 'B':
	PI[i] = wEnumB;
	continue;
      case 'b':
	PI[i] = bEnumB;
	continue;
      case 'N':
	PI[i] = wEnumN;
	continue;
      case 'n':
	PI[i] = bEnumN;
	continue;
      case 'P':
	PI[i] = wEnumP;
	continue;
      case 'p':
	PI[i] = bEnumP;
	continue;
      case 'Z':
	PI[i] = BlockedPawn;
	continue;
      default:
	PI[i] = 0;
      }
  POSITION->DYN_ROOT = malloc (MAXIMUM_PLY * sizeof(typeDYNAMIC));
  POSITION->DYN = POSITION->DYN_ROOT + 1;
  TripleBaseMake (POSITION, PI, I);
  free (POSITION->DYN_ROOT);
}
